package org.eda.act4;

public class SimpleLinkedList<T> implements ILinkedList<T> {

	// Atributos
	private Node<T> first;
	private Node<T> actual;

	// Constructor
	public SimpleLinkedList() {
		first = null;
		actual = null;
	}

	// Métodos publicos
	public void goFirst() {
		actual = first;
	}

	public void goNext() {
		if (actual != null)
			actual = actual.next;
	}

	public void goPrevious() {
		if (first != null) {
			if (first == actual)
				actual = null;
			else {
				Node<T> aux = first;
				while (aux.next != actual) {
					aux = aux.next;
				}
				actual = aux;
			}
		}
	}

	public void goLast() {
		if (first != null) {
			actual = first;
			while (actual.next != null) {
				actual = actual.next;
			}
		}
	}

	public boolean hasNext() {
		return (actual != null);
	}

	public boolean find(T elem) { 								
		boolean enc=false;
		Node<T> actual=first;
			while(actual!=null && !enc){
				if(actual.data.equals(elem)){
					enc=true;
				}else{
					actual=actual.next;
				}
			}
			
		if (!enc){
			actual=null;
		}
		
		return enc;
		

	}

	public void insert(T elem) {
		Node<T> nuevoNodo=new Node<T>(elem);
		if(actual==null || actual==first){
			this.insertFirst(elem);
			
		}else{
			nuevoNodo.next=actual;
			this.goPrevious();
			actual.next=nuevoNodo;
			this.goNext();
		}
	}

	public void insertFirst(T elem) {
		Node<T> newNode = new Node<T>(elem);
		newNode.next = first;
		first = newNode;
		actual = first;
	}

	public void insertLast(T elem) {
		Node<T> newNode = new Node<T>(elem);
		if(first==null){
			first=newNode;	
		}else{
		this.goLast();
		actual.next=newNode;
		newNode.next=null;
		}
		actual=newNode;
	}

	
	
public void insertIndex(T elem, int index){
	actual=first;
	int i=1;
	while (actual.next!=null && i<index-1){
		this.goNext();
		i=i+1;
	}
	
	this.insert(elem);
	
}

	public void remove(T elem) {
		if (first != null) {
			if (first.data.equals(elem))
				first = first.next;
			else {
				actual = first;
				Node<T> ant = null;
				while ((actual.next != null) && !(actual.data.equals(elem))) {
					ant = actual;
					actual = actual.next;
				}
				if (actual.data.equals(elem))
					ant.next = actual.next;
			} 
		}
		actual = first;
	};

	public void remove(){
        if (actual != null){    
        	if (first==actual){
	       		if (actual.next == null){
	       			actual = null;
	       			first = null;
	            }
	            else{
	                goNext();
                    first = actual;
                }
            }
            else if (actual.next == null){
                goPrevious();
                actual.next=null;
                actual = null;
            }
            else{
                Node<T> aux = first;
                while (aux.next != actual){
                    aux = aux.next;
                }
	                
            goNext();
            aux.next=actual;
            }
        }
    } 
	

	public T remove(int index) {
		Node<T> aux=actual;
		actual=first;
		int i=1;
		while (actual.next!=null && i<index-1){
			this.goNext();
			i=i+1;
		}
		Node<T> previo=actual;
		this.goNext();
		aux=actual;
		if (actual==first){
			first = actual.next;
			actual=actual.next;
		}
		else{	
			
			actual= previo;
			actual.next=aux.next;
		}
		this.goFirst();
		
		return aux.data;
	}

	public T get() {
		return actual.data;

	}

	public T get(int index) {
		// Pre: actual apunta a algún nodo

		actual=first;
		int i=1;
		while (actual.next!=null && i<index){
			this.goNext();
			i=i+1;
		}
		return actual.data;
	}

	public boolean isEmpty() {
		boolean vacio=false;
		if(first==null){
			vacio=true;
		}	 
		return vacio;
		
	}
	
	public int size(){
		return this.size();
	}
}
